/**
 * 
 */
package ac.svn.accesscontrol.manager;

import java.util.HashSet;
import java.util.Set;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import ac.notification.event.INotificationListener;
import ac.notification.event.NotificationEvent;
import ac.notification.manager.NotificationRegistrar;
import ac.svn.accesscontrol.controller.AboutMenuController;
import ac.svn.accesscontrol.controller.ApplcationPopupController;
import ac.svn.accesscontrol.controller.EntityDeletionHandler;
import ac.svn.accesscontrol.controller.FunctionKeyController;
import ac.svn.accesscontrol.controller.IdentifierChangeController;
import ac.svn.accesscontrol.controller.InformationAssembler;
import ac.svn.accesscontrol.controller.StatusLabelController;
import ac.svn.accesscontrol.controller.SystemNotificationController;
import ac.svn.accesscontrol.controller.TagEditorController;
import ac.svn.accesscontrol.controller.TagProcessor;
import ac.svn.accesscontrol.controller.ToolBarController;
import ac.svn.accesscontrol.controller.UIController;
import ac.svn.accesscontrol.controller.UserPasswordCreationController;
import ac.svn.accesscontrol.hooks.server.ConnectionServer;
import ac.svn.accesscontrol.io.AccessFileLoader;
import ac.svn.accesscontrol.io.AccessFileWriter;
import ac.svn.accesscontrol.io.ConfigFileHandler;
import ac.svn.accesscontrol.io.IConfigProvider;
import ac.svn.accesscontrol.store.Dictionary;
import ac.svn.accesscontrol.store.ISVNIdentifier;
import ac.svn.accesscontrol.ui.IUIConstants;
import ac.svn.accesscontrol.ui.UIComponentLibrary;
import ac.svn.accesscontrol.ui.window.ConfigFileSelectorDialog;
import ac.svn.accesscontrol.ui.window.MainWindow;
import ac.svn.accesscontrol.utils.Utility;

/**
 * @author Enigmanic
 *
 */
public class InitManager implements INotificationListener,ISVNIdentifier,IUIConstants{
	MainWindow 					mainWindow;
	TagProcessor 					tagProcessor;
	UIController 						uiController;
	IConfigProvider 				configProvider;
	ConfigFileSelectorDialog 	dialog;
	AccessFileLoader  				accessFileLoader;
	AccessFileWriter  				accessFileWriter;
	ConnectionServer 			connectionServer;
	ToolBarController 				toolbarController;
	UserInformationManager 		informationManager;
	TagEditorController 		tagEditorController;
	GroupsInformationManager 		groupsInformationManager;
	LocationInformationManager 		locationInformationManager;
	InformationAssembler		informationAssembler;
	SystemNotificationController 	systemNotificationController;
	StatusLabelController		statusLabelController;
	EntityDeletionHandler 		deletionHandler;
	IdentifierChangeController identifierChangeController;
	ApplcationPopupController applcationPopupController;
	AboutMenuController aboutMenuController;
	UserPasswordCreationController passwordCreationController;
	FunctionKeyController functionKeyController;
	
	public InitManager()
	{
		mainWindow 			= new MainWindow();
		systemNotificationController 	= new SystemNotificationController();
		
		mainWindow.setVisible(true);
		
		//Initialize Components
		initComponents();
		
		//Configure Components
		configureComponents();
		
		//Dispatch event to open/load file.
		startOperations();
	}
	
	private void initComponents()
	{
		Utility.sendNotification(N_GENERAL_PROGRESS_MSG,"Initializing components..");
		
		tagProcessor 						= new TagProcessor();
		uiController 						= new UIController();
		configProvider 					= new ConfigFileHandler();
		dialog 									= new ConfigFileSelectorDialog();
		accessFileLoader 				= new AccessFileLoader();
		accessFileWriter 				= new AccessFileWriter();
		toolbarController 				= new ToolBarController();
		informationManager 		= new UserInformationManager();
		tagEditorController 			= new TagEditorController();
		groupsInformationManager 	= new GroupsInformationManager();
		locationInformationManager 	= new LocationInformationManager();
		informationAssembler 				= new InformationAssembler();
		applcationPopupController 		= new ApplcationPopupController();
		
		statusLabelController			= new StatusLabelController();
		deletionHandler						= new EntityDeletionHandler();
		identifierChangeController 	= new IdentifierChangeController();
		aboutMenuController			= new AboutMenuController();
		functionKeyController			= new FunctionKeyController(mainWindow);
		passwordCreationController = new UserPasswordCreationController();
		
		Utility.sendNotification(N_GENERAL_COMPLETION_MSG ,"Initialization Completed!");
	}
	
	private void configureComponents()
	{
		Utility.sendNotification(N_GENERAL_PROGRESS_MSG,"Configuring components..");
		
		IntellisenseManager.getIntellisenseManager().setMainWindow(mainWindow);
		JLabel statusLabel = (JLabel) UIComponentLibrary.getComponent(C_STATUS_LABEL);
		statusLabelController.setStatusLabel(statusLabel);

		Utility.sendNotification(N_GENERAL_INFO_MSG,"Reading configuration..");
		
		//Read dictionary values from configuration file.
		Dictionary dictionary = Dictionary.getDictionary();
		configProvider.readConfiguration(Dictionary.configFileName,dictionary);
		
		Utility.sendNotification(N_GENERAL_COMPLETION_MSG,"Configuration Completed!");
	}
	
	private void startOperations()
	{
		Utility.sendNotification(N_GENERAL_PROGRESS_MSG,"Starting Operations..");
		
		Dictionary dictionary = Dictionary.getDictionary();
		
		NotificationEvent event = null;
		if(false == dictionary.isAlwaysOpen())
		{
			event = new NotificationEvent(ISVNIdentifier.CMD_OPEN_FILE);
		}
		else
		{
			event = new NotificationEvent(ISVNIdentifier.CMD_PROCESS_FILE);
		}
		event.setPropertyValue(dictionary.getLastAccessFile().getAccessFileLocation());
		NotificationRegistrar.dispatchNotification(event)	;
		NotificationRegistrar.registerListener(this);

		//Sync User details with file data
		event = new NotificationEvent(N_UIM_SYNC_USER_INFO);
		NotificationRegistrar.dispatchNotification(event);
	}
	@Override
	public Set<String> declaredSubscriptionSet() 
	{
		Set<String> subscriptionSet = new HashSet<String>(1);
		subscriptionSet.add(CMD_EXIT_SYSTEM);
		subscriptionSet.add(CMD_SAVE_CONFIG);
		return subscriptionSet;
	}
	@Override
	public void receiveEvent(NotificationEvent ne)
	{
		if(ne.getPropertyIdentifier().contains(CMD_EXIT_SYSTEM))
		{
			SwingUtilities.invokeLater(new Runnable() 
			{
				@Override
				public void run() 
				{
					exitHandler();					
				}
			});
		}
		else if(ne.getPropertyIdentifier().contains(CMD_SAVE_CONFIG))
		{
			saveConfigHandler();
		}

	}

	private void saveConfigHandler() 
	{
		Utility.iconCache.save();
		if(configProvider.saveConfiguration(Dictionary.configFileName, Dictionary.getDictionary()))
		{
			Utility.sendNotification(N_CONFIG_SAVED);   
		}
		else
		{
			Utility.sendNotification(N_CONFIG_SAVING_FAILED);
		}


	}
	private void exitHandler()
	{
		configProvider.saveConfiguration(Dictionary.configFileName, Dictionary.getDictionary());
		//System.exit(0);
		int selectedOption  =JOptionPane.showConfirmDialog(mainWindow, "Sure,  you want to exit?","Exit", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
		if(JOptionPane.YES_OPTION == selectedOption )
		{
			System.exit(0);
		}
		else
		{
			mainWindow.setVisible(true);
		}
	}

	public MainWindow getMainWindow() {
		return mainWindow;
	}
}
